// 题意：给定n(<=10000)个点，m(<=50000)条边，q(<=10000)个询问li，问有多少点对满足
//       满足他们的费用小于等于li，它们的费用定义为连接两点所有路中，路径最大值
//       的最小值。
//
// 题解：直接在线做比较难。所以考虑离线。将边和询问li排序，从小到大做询问，
//       从小到大加边，然后并查集维护，并且实时维护答案，和每块联通大小。
//
// 统计：202ms, 25min, 1a
//
// run: $exec < input
#include <cstdio>
#include <algorithm>

struct query { int l; int pos; };

bool operator<(query const & a, query const & b)
{
	return a.l < b.l;
}

struct edge { int from; int to; int cost; };

bool operator<(edge const & a, edge const & b)
{
	return a.cost < b.cost;
}

int const maxn = 10100;
int const maxm = 50100;
int const maxq = 10100;
edge edges[maxm];
query queries[maxq];
int parent[maxn], count[maxn];
int n, m, q;

long long query_ans[maxq];
long long ans;

void init()
{
	for (int i = 1; i <= n; i++) {
		parent[i] = i;
		count[i] = 1;
	}
	ans = 0;
}

int get_parent(int u)
{
	return u == parent[u] ? u : (parent[u] = get_parent(parent[u]));
}

long long c2(long long u)
{
	return u < 2 ? 0 : u * (u - 1) / 2;
}

void set_union(int u, int v)
{
	int tu = get_parent(u);
	int tv = get_parent(v);
	if (tu != tv) {
		ans -= c2(count[tu]) + c2(count[tv]) - c2(count[tu] + count[tv]);
		parent[tu] = tv;
		count[tv] += count[tu];
	}
}

int main()
{
	while (std::scanf("%d %d %d", &n, &m, &q) != EOF) {
		init();

		for (int i = 0; i < m; i++)
			std::scanf("%d %d %d", &edges[i].from, &edges[i].to, &edges[i].cost);
		for (int i = 0; i < q; i++) {
			std::scanf("%d", &queries[i].l);
			queries[i].pos = i;
		}
		std::sort(edges, edges + m);
		std::sort(queries, queries + q);

		int now = 0;
		for (int i = 0; i < q; i++) {
			for (; now < m && edges[now].cost <= queries[i].l; now++)
				set_union(edges[now].from, edges[now].to);
			query_ans[queries[i].pos] = ans;
		}
		for (int i = 0; i < q; i++)
			std::printf("%lld\n", query_ans[i]);
	}
}

